package com.h3c.nem.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eos.common.util.CustomBeanUtils;
import com.eos.common.util.IdWorker;
import com.h3c.nem.async.AsyncSendMessage;
import com.h3c.nem.cache.TbOfferWorkerCache;
import com.h3c.nem.client.AbilityClient;
import com.h3c.nem.config.SpringUtil;
import com.h3c.nem.dto.beisen.*;
import com.h3c.nem.entity.*;
import com.h3c.nem.enums.*;
import com.h3c.nem.mapper.*;
import com.h3c.nem.sap.RfcManager;
import com.h3c.nem.utils.AppBusinessException;
import com.h3c.nem.utils.BusiEnumDefine;
import com.h3c.nem.utils.EncryptionUtil;
import com.h3c.nem.utils.EnumUtil;
import com.sap.conn.jco.*;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * @Title:
 * @Description: 北森接口
 * @Params:
 * @Return:
 * @Author: f23104
 * @Time: 2022/6/8 10:48
 */
@Service
@Slf4j
public class BeiSenService {

    @Value("${ptability.token}")
    private String ptToken;
    @Value("${beisen.token}")
    private String beisenToken;
    @Value("${beisen.getOffer.url}")
    private String offerUrl;
    @Value("${beisen.getInfo.url}")
    private String infoUrl;
    @Value("${beisen.filePrefix.url}")
    private String picPrefix;
    @Value("${ocr.url}")
    private String ocrUrl;
    @Value("${beisen.syncPreId.url}")
    private String syncPreIdUrl;
    @Value("${beisen.getHired.url}")
    private String getHiredUrl;
    @Value("${beisen.sync.workerStatus.url}")
    private String syncWorkerStatusUrl;
    @Value("${beisen.appid}")
    private String appId;
    @Value("${reg.url}")
    private String regUrl;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    RestTemplate httpsRestTemplateForUid;
    @Resource
    CommService commService;
    @Resource
    private RfcManager rfcManager;
    @Resource
    private AbilityClient abilityClient;
    @Autowired
    private BeiSenService beiSenService;
    @Value("${ptability.appId}")
    private String ptAppId;
    @Value("${ability.url}")
    private String abilityUrl;
    @Value("${sap.notice.mail}")
    private String sapNoticeMail;
    @Resource
    AsyncSendMessage asyncSendMessage;
    @Resource
    ISdEmailTemplateService emailTemplateService;
    @Resource
    private TbOfferAttachmentMapper tbOfferAttachmentMapper;
    @Resource
    private TbApprovalRecordMapper tbApprovalRecordMapper;
    @Resource
    private TbOfferWorkerMapper tbOfferWorkerMapper;
    @Resource
    private TbOfferContactorMapper tbOfferContactorMapper;
    @Resource
    private TbOfferFamilyMapper tbOfferFamilyMapper;
    @Resource
    private TbOfferLanguageMapper tbOfferLanguageMapper;
    @Resource
    private TbOfferStudyMapper tbOfferStudyMapper;
    @Resource
    private TbWorkerExperienceMapper tbWorkerExperienceMapper;
    @Resource
    private ThreadPoolService threadPoolService;
    @Resource
    private SdRequestRecordService sdRequestRecordService;

    @Data
    public static class ReturnDTO {
        private Integer code;

        private Boolean success;

        private String message;

        private String data;
    }


    /**
     * 北森offer信息接口
     * "Offer可能有多条，获取offerState !=3，4（状态不是已拒绝、已失效时）的offer
     * 多条offer时，使用EndApprovalTime最大的一条（认为最新）"
     *
     * @param beiSenNumber
     * @return
     */
    public BeiSenOfferDTO getBeiSenOffer(String beiSenNumber) {
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(beisenToken);
        headers.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<String> response = httpsRestTemplateForUid.exchange(offerUrl + beiSenNumber, HttpMethod.GET, new HttpEntity<>(headers), String.class);
        log.info("获取北森 " + beiSenNumber + " 的offer信息===============================");
        log.info(response.toString());
        log.info("===============================================================");
        String body = response.getBody();
        if (StringUtils.hasText(body)) {
            log.info("转北森 " + beiSenNumber + " 的offer对象============================");
            List<BeiSenOfferDTO> beiSenOfferDTOS = JSONArray.parseArray(body, BeiSenOfferDTO.class);
            log.info(String.valueOf(beiSenOfferDTOS));
            log.info("=================================================================");
            BeiSenOfferDTO retDTO = null;
            if (beiSenOfferDTOS.size() > 0) {
                for (BeiSenOfferDTO offerDTO : beiSenOfferDTOS) {
                    List<BeiSenOfferDTO.ExtProp> extendInfos = offerDTO.getExtendInfos();
                    String offerState = null;
                    for (BeiSenOfferDTO.ExtProp info : extendInfos) {
                        if (info.getName().equals("OfferState")) {
                            offerState = info.getValue();
                            break;
                        }
                    }
                    if (StringUtils.hasText(offerState) && !offerState.equals("3") && !offerState.equals("4")) {
                        if (retDTO == null) {
                            retDTO = offerDTO;
                        } else {
                            SimpleDateFormat sdf = new SimpleDateFormat("y/M/d h:m:s");
                            try {
                                if (StringUtils.hasText(offerDTO.getEndApprovalTime())
                                        && StringUtils.hasText(retDTO.getEndApprovalTime())
                                        && sdf.parse(offerDTO.getEndApprovalTime()).compareTo(sdf.parse(retDTO.getEndApprovalTime())) > 0) {
                                    retDTO = offerDTO;
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                if (retDTO == null) {
                    throw new AppBusinessException(beiSenNumber + " 未获取到有效的Offer");
                }
            }
            return retDTO;
        } else {
            return null;
        }
    }

    /**
     * 同步员工状态到北森
     *
     * @param offerWorker
     */
    @Async
    public void syncWorkerStatusToBeiSen(TbOfferWorker offerWorker) {
        if (StringUtils.isEmpty(offerWorker.getDataSource()) || "BPM".equals(offerWorker.getDataSource())) {
            return;
        }
        try {
            String urlString = "/" + URLEncoder.encode(offerWorker.getWorkerName(), "UTF-8") + "/-/" +
                    offerWorker.getPhoneNo() + "/-/-?idType=1&language=1";

            boolean codeFlag = Objects.equals(offerWorker.getWorkerStatus(), OfferWorkerStatusEnum.取消入职);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Host", "api.beisenapp.com");
            headers.set("Connection", "Keep-Alive");
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.setBearerAuth(beisenToken);
            HttpEntity<String> req = new HttpEntity<>(headers);
            ResponseEntity<String> response = httpsRestTemplateForUid.exchange(getHiredUrl + urlString, HttpMethod.POST, req, String.class);
            log.info("获取北森 " + offerWorker.getWorkerName() + " 的jobId===============================");
            log.info(response.toString());
            log.info("===============================================================");
            String body = response.getBody();
            if (StringUtils.hasText(body)) {
                log.info("转北森 " + offerWorker.getWorkerName() + " 的对象============================");
                List<BeiSenInfoDTO> beiSenInfoDTOList = JSONArray.parseArray(body, BeiSenInfoDTO.class);
                log.info(String.valueOf(beiSenInfoDTOList));
                log.info("=================================================================");
                if (beiSenInfoDTOList.isEmpty()) {
                    log.error("没有找到北森对象");
                    return;
                }
                BeiSenInfoDTO beiSenInfoDTO = beiSenInfoDTOList.get(0);
                List<BeiSenInfoDTO.BeiSenApplyJobSummaries> jobSummaries = beiSenInfoDTO.getApplyJobSummaries();
                log.info(jobSummaries.toString());
                for (BeiSenInfoDTO.BeiSenApplyJobSummaries job : jobSummaries) {
                    try {
                        syncWorkerStatus(StringUtils.isEmpty(offerWorker.getBeiSenId()) ? beiSenInfoDTO.getApplicantId() : offerWorker.getBeiSenId(), job.getJobId(), "S12", codeFlag ? "U13" : "U12");
                    } catch (Exception e) {
                        log.error(offerWorker.getWorkerName() + "执行同步北森异常", e);
                    }
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步员工状态
     *
     * @param workerId 北森员工id
     * @param jobId    工号id
     * @param phaseId  阶段
     * @param status   状态
     * @return
     */
    public void syncWorkerStatus(String workerId, String jobId, String phaseId, String status) {
        String inputData = "applicant_ids=" + workerId + "&job_id=" + jobId + "&phase_id=" + phaseId + "&status_id=" + status;
        log.info("调用北森接口同步员工接口：" + inputData);
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(beisenToken);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<String> req = new HttpEntity<>(inputData, headers);
        ResponseEntity<String> response = httpsRestTemplateForUid.exchange(syncWorkerStatusUrl, HttpMethod.POST, req, String.class);
        log.info(response.toString());
        String body = response.getBody();
        if (StringUtils.hasText(body)) {
            log.info("转北森的基本信息对象：" + body);
            JSONObject jsonObject = JSONObject.parseObject(body);
            if (Objects.equals(jsonObject.getString("code"), "200")) {
                log.info("同步员工[" + workerId + "/" + jobId + "]成功");
            } else {
                log.info("同步员工[" + workerId + "/" + jobId + "]失败");
            }
        } else {
            log.error("调用北森接口同步员工接口异常");
        }
    }

    /**
     * 北森info信息接口
     *
     * @param beiSenNumber
     * @return
     */
    public BeiSenInfoDTO getBeiSenInfo(String beiSenNumber) {
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(beisenToken);
        headers.setContentType(MediaType.APPLICATION_JSON);
        //北森基本信息GET接口固定参数
        String infoUrlSuffix = "?language=1&photo_base64=0&has_Long=1";
        ResponseEntity<String> response = httpsRestTemplateForUid.exchange(infoUrl + beiSenNumber + infoUrlSuffix, HttpMethod.GET, new HttpEntity<>(headers), String.class);
        log.info("获取北森 " + beiSenNumber + " 的基本信息===============================");
        log.info(String.valueOf(response));
        log.info("===============================================================");
        String body = response.getBody();
        if (StringUtils.hasText(body)) {
            log.info("转北森 " + beiSenNumber + " 的基本信息对象=============================");
            List<BeiSenInfoDTO> beiSenInfoDTOS = JSONArray.parseArray(body, BeiSenInfoDTO.class);
            log.info(String.valueOf(beiSenInfoDTOS));
            log.info("===================================================================");
            return beiSenInfoDTOS.size() > 0 ? beiSenInfoDTOS.get(0) : null;
        } else {
            return null;
        }
    }

    /**
     * 推送预备员工号给北森
     *
     * @param beiSenNumber
     * @param preWorkerId
     * @param errorMsg
     */
    public void syncPreWorkerIdToBeiSen(String beiSenNumber, String preWorkerId, String errorMsg) {
        String fieldName;
        String value;
        //失败时
        if (StringUtils.hasText(errorMsg)) {
            fieldName = "extfailreason_105130_1458142282";
            value = errorMsg;
        } else {
            fieldName = "extybygbh_105130_1881359711";
            value = preWorkerId;
        }
        try {
            value = URLEncoder.encode(value, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String inputData = "Tenant_id=" + appId + "&applicant_id=" + beiSenNumber + "&user_id=0&field_values=[{\"PropertyName\":\"" + fieldName + "\",\"PropertyShortName\":\"" + fieldName + "\",\"Code\":\"\",\"Value\":\"" + value + "\"}]";
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(beisenToken);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        log.info("推送预备工号至北森================================");
        log.info("北森编号" + beiSenNumber);
        log.info("预备工号" + preWorkerId);
        log.info("错误信息" + errorMsg);
        log.info(inputData);
        log.info("=================================================================");

        HttpEntity<String> req = new HttpEntity<>(inputData, headers);
        ResponseEntity<String> response = httpsRestTemplateForUid.exchange(syncPreIdUrl, HttpMethod.POST, req, String.class);
        String responseBody = response.getBody();
        log.info("推送预备工号至北森 返回 =============================");
        log.info("北森编号" + beiSenNumber);
        log.info("预备工号" + preWorkerId);
        log.info("错误信息" + errorMsg);
        log.info(responseBody);
        log.info("===================================================================");
        /*
        Code	返回数据编码	1或者0（0：失败，1：成功）
        Data	返回数据	泛型T（数字、字符串、布尔型）
        Description	描述	字符串
         */
        Object code = JSONObject.parseObject(responseBody).get("Code");
        if (!(code != null && code.equals(1))) {
            throw new AppBusinessException("推送预备员工号" + beiSenNumber + "至北森异常");
        }
    }

    /**
     * 北森调用的接口
     *
     * @param beiSenList
     */
    public List<ReturnDTO> func(List<String> beiSenList) {
        Map<String, String> exceptionMap = new ConcurrentHashMap<>();
        if (CollectionUtils.isEmpty(beiSenList)) {
            return new ArrayList<>();
        }
        log.info("start time~~~~~~~~~{}", System.currentTimeMillis());
        List<BeiSenBuildDTO> collect = new Vector<>();

        CountDownLatch latch = new CountDownLatch(beiSenList.size());
        beiSenList.forEach(beiSenId -> {
            Thread thread = new Thread(() -> {
                try {
                    BeiSenBuildDTO buildDTO = beiSenService.buildBeiSenDTO(beiSenId);
                    collect.add(buildDTO);
                } catch (Exception e) {
                    e.printStackTrace();
                    exceptionMap.put(beiSenId, e.getMessage());
                    collect.add(null);
                } finally {
                    latch.countDown();
                }
            });
            threadPoolService.submitTask(thread);
            log.info("add thread {}", beiSenId);
        });

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //保存构建好的预备员工数据
        if (!CollectionUtils.isEmpty(collect)) {
            collect.forEach(dto -> {
                if (dto != null) {
                    try {
                        SpringUtil.getBean(BeiSenService.class).anotherTransactional(dto.getBeiSenNumber(),
                                dto.getBeiSenInfo(),
                                dto,
                                dto.getWorkerStatus(),
                                dto.getIdCardUrlMap(),
                                dto.getExistFlag(),
                                dto.getDeleteFlag());
                    } catch (Exception e) {
                        e.printStackTrace();
                        exceptionMap.put(dto.getBeiSenNumber(), e.getMessage());
                    }
                }
            });
        }

        List<String> preWorkerIds = new ArrayList<>();
        List<ReturnDTO> returnDTOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(collect)) {
            collect.forEach(dto -> {
                if (dto != null) {
                    OfferWorker offerWorker = dto.getTbOfferWorker();
                    ReturnDTO ret = new ReturnDTO();
                    ret.setCode(1);
                    ret.setSuccess(true);
                    ret.setMessage("预备工号创建完成[" + offerWorker.getWorkerId() + "]");
                    ret.setData(offerWorker.getBeiSenId());
                    returnDTOS.add(ret);
                    //更新信息的不发通知给员工
                    if (dto.getExistFlag() != null && !dto.getExistFlag()) {
                        sendNoticeToWorker("PRE_WORKER_EMAIL",
                                offerWorker.getWorkerName(),
                                offerWorker.getEmail(),
                                null, offerWorker.getCertNo(),
                                "H3C" + StrUtil.sub(offerWorker.getCertNo(), -4, offerWorker.getCertNo().length()));
                        sendNoticeToWorker("PRE_WORKER_SMS",
                                offerWorker.getWorkerName(),
                                null,
                                offerWorker.getPhoneNo(),
                                offerWorker.getCertNo(),
                                "H3C" + StrUtil.sub(offerWorker.getCertNo(), -4, offerWorker.getCertNo().length()));
                        preWorkerIds.add(offerWorker.getWorkerId());
                    }
                }
            });
        }
        exceptionMap.forEach((k, v) -> {
            ReturnDTO ret = new ReturnDTO();
            ret.setCode(10);
            ret.setSuccess(false);
            ret.setMessage("预备工号创建异常[" + v + "]");
            ret.setData(k);
            returnDTOS.add(ret);
        });

        asyncSendMessage.sendMailToRelated(preWorkerIds);
        log.info("入参{}\n, 出参{}", beiSenList, returnDTOS);
        log.info("end time~~~~~~~~~{}", System.currentTimeMillis());
        return returnDTOS;
    }

    /**
     * 调用北森查询信息接口生成预备工号返回给北森并保存  如果调用北森查询信息的接口返回带有预备工号。则进行数据的更新。不生成预备工号
     *
     * @param beiSenNumber
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public BeiSenBuildDTO buildBeiSenDTO(String beiSenNumber) {
        long start = System.currentTimeMillis();
        log.info("1.调用北森offer接口 {}~~~~~~~~~~~~", beiSenNumber);
        BeiSenOfferDTO beiSenOffer = getBeiSenOffer(beiSenNumber);
        if (beiSenOffer == null) {
            throw new AppBusinessException(beiSenNumber + " 北森offer接口返回或解析异常");
        }
        log.info("2.调用北森info接口 {}~~~~~~~~~~~~", beiSenNumber);
        BeiSenInfoDTO beiSenInfo = getBeiSenInfo(beiSenNumber);
        if (beiSenInfo == null) {
            throw new AppBusinessException(beiSenNumber + " 北森info接口返回或解析异常");
        }

        log.info("3.组装员工参数 {}~~~~~~~~~~~~", beiSenNumber);
        BeiSenBuildDTO buildDTO = new BeiSenBuildDTO();
        Map<String, BiConsumer<BeiSenBuildDTO, Object>> offerMap = offerMapForPropConsumer();
        Map<String, BiConsumer<BeiSenBuildDTO, Object>> infoMap = infoMapForPropConsumer();

        log.info("3-1.组装offer返回参数 {}~~~~~~~~~~~~", beiSenNumber);
        //offer接口的extendInfos属性
        List<BeiSenOfferDTO.ExtProp> extendInfos = beiSenOffer.getExtendInfos();
        offerMap.forEach((k, v) -> {
            extendInfos.forEach(extend -> {
                if (extend.getName().equals(k)) {
                    if (k.equals("Post")        //岗位
                            || k.equals("extNationality_105130_586467707")  //新国籍
                            || k.equals("extSAPWorkPlace_105130_1432849287")//新工作履行地
                    ) {
                        v.accept(buildDTO, extend.getText());
                    } else {
                        v.accept(buildDTO, extend.getValue());
                    }
                }
            });
        });
        log.info("3-2.组装info返回参数 {}~~~~~~~~~~~~", beiSenNumber);
        //info接口的profile属性
        List<BeiSenInfoDTO.BeiSenItems> profileInfos = beiSenInfo.getProfile().getItems();
        infoMap.forEach((k, v) -> {
            profileInfos.forEach(profile -> {
                if (profile.getPropertyName().equals(k)) {
                    v.accept(buildDTO, profile.getValue());
                }
            });
        });

        log.info("4.判断身份证 进行OCR {}~~~~~~~~~~~~", beiSenNumber);
        OfferWorker offerWorker = buildDTO.getTbOfferWorker();
        //测试使用 记得注释
//        if (offerWorker.getPlanReportDate() == null) {
//            offerWorker.setPlanReportDate(new Date());
//        }
        OfferWorkerStatusEnum workerStatus = OfferWorkerStatusEnum.待填写入职资料;
        Date applyReportDate = null;
        String applyChangeReason = null;
        //北森来的身份证
        String beiSenCertNo = offerWorker.getCertNo();
        //是否存在预备工号
        boolean existFlag = StringUtils.hasText(offerWorker.getWorkerId());
        //证件类型是身份证 进行OCR 与输入的身份证和姓名匹配。不一致则直接返回，若OCR失败则不管
        IdTypeEnum idType = offerWorker.getCertType();
        //正面 反面  map
        Map<String, String> idCardUrlMap = new HashMap<>();
        if (IdTypeEnum.ID_CARD.equals(idType)) {
            //身份证全变成大写字母
            offerWorker.setCertNo(offerWorker.getCertNo().toUpperCase());
            String idCardPics = offerWorker.getIdCardPics();
            if (StringUtils.hasText(idCardPics)) {
                OcrDTO finalDTO = new OcrDTO();
                for (String picUrl : idCardPics.split(",")) {
                    String picType = picUrl.substring(picUrl.lastIndexOf(".")).toLowerCase();
                    if (!checkImgType(picType)) {
                        continue;
                    }
                    String imgUrl = replacePicUrl(picUrl);
                    //正面或反面的ocr结果
                    OcrDTO ocrDTO = idCardOcr(imgUrl);

                    if (ocrDTO != null) {
                        log.info("{} OCR识别结果：{}", beiSenNumber, ocrDTO);
                        if (StringUtils.hasText(ocrDTO.getName())) {
                            idCardUrlMap.put("front", picUrl);
                        } else if (StringUtils.hasText(ocrDTO.getValidDate())) {
                            idCardUrlMap.put("back", picUrl);
                        }
                        CustomBeanUtils.copyProperties(ocrDTO, finalDTO, false, false);
                    }
                }
                checkOcrResult(finalDTO, offerWorker);
            }
        }
        //更新信息不给员工发邮件和短信
        buildDTO.setExistFlag(existFlag);
        boolean deleteFlag = false;
        //有预备工号的进行数据更新 没有预备工号的生成预备工号推送给北森
        if (!existFlag) {
            log.info("5.北森返回没有预备工号，准备调用SAP生成预备工号 {}~~~~~~~~~~~~", beiSenNumber);

            log.info("组装北森数据用于调SAP： {}", buildDTO);
            log.info("5-1.调用SAP生成预备工号 {}~~~~~~~~~~~~", beiSenNumber);
            Map<String, String> sapReturnMap = callSapForPreWorkerNumber(buildDTO);
            log.info("5-2.返回预备工号回北森 {}~~~~~~~~~~~~", beiSenNumber);
            syncPreWorkerIdToBeiSen(beiSenNumber, sapReturnMap.get("preId"), sapReturnMap.get("msg"));
            if (StringUtils.hasText(sapReturnMap.get("msg"))) {
                log.info("5-3.预备工号生成异常，通知相关人员 {}~~~~~~~~~~~~", beiSenNumber);
                sendExceptionMsg(beiSenInfo, offerWorker.getWorkerName(), sapReturnMap.get("msg"), beiSenNumber, offerWorker.getCertNo());
                throw new AppBusinessException("生成预备工号失败：" + sapReturnMap.get("msg"));
            }
            log.info("5-2.返回预备工号回北森完毕 {} 预备工号：{} 异常信息：{}~~~~~~~~~~~~", beiSenNumber, sapReturnMap.get("preId"), sapReturnMap.get("msg"));
            //推送完数据开始保存到自己数据库
            //预备员工号
            offerWorker.setWorkerId(sapReturnMap.get("preId"));
            //员工直属部门
            offerWorker.setDirectDeptId(sapReturnMap.get("directDeptId"));
            offerWorker.setPreparationPassword(EncryptionUtil.encodeForBeiSenAndSap(offerWorker.getCertNo()));
            offerWorker.setWorkerStatus(workerStatus);
        } else {
            log.info("5.北森返回存在预备工号，准备更新本地数据库信息 {}~~~~~~~~~~~~", beiSenNumber);
            TbOfferWorker existWorker = tbOfferWorkerMapper.selectById(offerWorker.getWorkerId());
            if (existWorker == null) {
                throw new AppBusinessException("预备员工：" + offerWorker.getWorkerId() + "不存在");
            }
            workerStatus = existWorker.getWorkerStatus();
            applyReportDate = existWorker.getApplyReportDate();
            applyChangeReason = existWorker.getApplyChangeReason();
            if (workerStatus.getCode() >= OfferWorkerStatusEnum.待审核入职资料.getCode()) {
                log.info("5-1.本地数据库中员工状态已到审核后，不操作 {}~~~~~~~~~~~~", beiSenNumber);
                //员工状态大于等于此则不处理
            } else {
                log.info("5-1.调用SAP更新预备员工信息 {}~~~~~~~~~~~~", beiSenNumber);
                Map<String, String> sapReturnMap = callSapForUpdatePreWorker(buildDTO);
                if (StringUtils.hasText(sapReturnMap.get("msg"))) {
                    log.info("更新SAP预备员工信息异常 {}~~~~~~~~~~~~", beiSenNumber);
                    throw new AppBusinessException("更新SAP预备员工信息异常：" + sapReturnMap.get("msg"));
                }
                log.info("5-2.保留offerWorker中的员工状态以及申请变更报到日期的记录，删除其余表内此员工的数据 {}~~~~~~~~~~~~", beiSenNumber);
                offerWorker.setWorkerStatus(workerStatus);
                offerWorker.setApplyReportDate(applyReportDate);
                offerWorker.setApplyChangeReason(applyChangeReason);
                offerWorker.setDirectDeptId(sapReturnMap.get("directDeptId"));
                offerWorker.setPreparationPassword(existWorker.getPreparationPassword());
                QueryWrapper<TbOfferWorker> workerWrapper = new QueryWrapper<>();
                workerWrapper.eq("worker_id", offerWorker.getWorkerId());
                tbOfferWorkerMapper.delete(workerWrapper);
                deleteFlag = true;
                TbOfferWorkerCache.deleteFillStatus(offerWorker.getWorkerId());
            }
        }
        saveWorkerData(buildDTO);

        buildDTO.setBeiSenNumber(beiSenNumber);
        buildDTO.setBeiSenInfo(beiSenInfo);
        buildDTO.setWorkerStatus(workerStatus);
        buildDTO.setIdCardUrlMap(idCardUrlMap);
        buildDTO.setExistFlag(existFlag);
        buildDTO.setDeleteFlag(deleteFlag);

        log.info(beiSenNumber + "线程耗时" + (System.currentTimeMillis() - start) / 1000);
        return buildDTO;
    }

    @Transactional(rollbackFor = Exception.class, propagation= Propagation.REQUIRES_NEW)
    public void anotherTransactional(String beiSenNumber,
                                     BeiSenInfoDTO beiSenInfo,
                                     BeiSenBuildDTO buildDTO,
                                     OfferWorkerStatusEnum workerStatus,
                                     Map<String, String> idCardUrlMap,
                                     boolean existFlag,
                                     boolean deleteFlag) {
        OfferWorker offerWorker = buildDTO.getTbOfferWorker();
        //为了防止更新预备员工信息时两个事务而导致的锁表。把删除老数据的操作也放到这个新事务里
        if (deleteFlag) {
            deleteOldData(offerWorker.getWorkerId());
        }
        log.info("6.填充学历、家庭信息、工作经历等详细信息 {}~~~~~~~~~~~~", beiSenNumber);
        fillOtherInfo(buildDTO, beiSenInfo);
        if (workerStatus.getCode() >= OfferWorkerStatusEnum.待审核入职资料.getCode()) {
            //员工状态大于等于此则不处理
            log.info("7.本地数据库中员工状态已到审核后，不操作 {}~~~~~~~~~~~~", beiSenNumber);
        } else {
            log.info("7.保存身份证图片 {}~~~~~~~~~~~~", beiSenNumber);
            if (idCardUrlMap.get("front") != null) {
                saveAttachment(offerWorker.getWorkerId(), idCardUrlMap.get("front"), TbOfferAttachment.ID_CARD_FRONT);
            }
            if (idCardUrlMap.get("back") != null) {
                saveAttachment(offerWorker.getWorkerId(), idCardUrlMap.get("back"), TbOfferAttachment.ID_CARD_BACK);
            }
            log.info("8.发送邮件/短信 {}~~~~~~~~~~~~", beiSenNumber);
            log.info("9.插入approvalRecord {}~~~~~~~~~~~~", beiSenNumber);
            if (existFlag) {
                addApprovalRecord(offerWorker.getWorkerId(), "员工信息重新初始化");
            } else {
                addApprovalRecord(offerWorker.getWorkerId(), "员工信息初始化");
            }
            log.info("10.保存其余附件 {}~~~~~~~~~~~~", beiSenNumber);
            saveBeiSenAttachment(buildDTO);
            log.info("11.保存各表数据 {}~~~~~~~~~~~~", beiSenNumber);
            saveOfferData(buildDTO);
        }

    }

    /**
     * 北森信息写入 插approvalRecord记录
     *
     * @param workerId
     * @param msg
     */
    public void addApprovalRecord(String workerId, String msg) {
        TbApprovalRecord record = new TbApprovalRecord();
        record.setApprovalId(IdWorker.nextId() + "");
        record.setFlowId(workerId);
        record.setFlowArriveTime(new Date());
        record.setApprovalType(BusiEnumDefine.APPROVAL_TYPE_BEISEN_SYNC);
        record.setApprovalTime(new Date());
        record.setApprovalNote(msg);
        tbApprovalRecordMapper.insert(record);
    }

    /**
     * 清理数据
     *
     * @param beiSenNumber
     */
    public void deleteOldData(String beiSenNumber) {
        QueryWrapper<TbOfferAttachment> attachmentWrapper = new QueryWrapper<>();
        QueryWrapper<TbOfferLanguage> languageWrapper = new QueryWrapper<>();
        QueryWrapper<TbOfferContactor> contactorWrapper = new QueryWrapper<>();
        QueryWrapper<TbOfferFamily> familyWrapper = new QueryWrapper<>();
        QueryWrapper<TbOfferStudy> studyWrapper = new QueryWrapper<>();
        QueryWrapper<TbWorkerExperience> expWrapper = new QueryWrapper<>();

        attachmentWrapper.eq("worker_id", beiSenNumber);
        languageWrapper.eq("worker_id", beiSenNumber);
        contactorWrapper.eq("worker_id", beiSenNumber);
        familyWrapper.eq("worker_id", beiSenNumber);
        studyWrapper.eq("worker_id", beiSenNumber).eq("is_beisen_data", 1);
        expWrapper.eq("worker_id", beiSenNumber).eq("is_beisen_data", 1);

        tbOfferAttachmentMapper.delete(attachmentWrapper);
        tbOfferLanguageMapper.delete(languageWrapper);
        tbOfferContactorMapper.delete(contactorWrapper);
        tbOfferFamilyMapper.delete(familyWrapper);
        tbOfferStudyMapper.delete(studyWrapper);
        tbWorkerExperienceMapper.delete(expWrapper);
    }

    public void saveWorkerData(BeiSenBuildDTO buildDTO) {
        //员工
        OfferWorker offerWorker = buildDTO.getTbOfferWorker();
        if (offerWorker != null) {
            TbOfferWorker tbOfferWorker = new TbOfferWorker();
            CustomBeanUtils.copyProperties(offerWorker, tbOfferWorker);
            String workerId = tbOfferWorker.getWorkerId();
            String directDeptId = offerWorker.getDirectDeptId();
            if (StringUtils.hasText(directDeptId)) {
                SdDept dept = commService.getDept(Integer.valueOf(directDeptId));
                if (dept != null) {
                    String deptNameChain = dept.getDeptNameChain();
                    String replace = deptNameChain.replace("新华三/", "");
                    tbOfferWorker.setDeptNameChain(replace);
                    tbOfferWorker.setDept1name(null);
                    tbOfferWorker.setDept2name(null);
                    tbOfferWorker.setDept3name(null);
                    tbOfferWorker.setDept4name(null);
                    String[] split = replace.split("/");
                    for (int i = 0; i < split.length; i++) {
                        String deptName = split[i];
                        if (i == 0) {
                            tbOfferWorker.setDept1name(deptName);
                        } else if (i == 1) {
                            tbOfferWorker.setDept2name(deptName);
                        } else if (i == 2) {
                            tbOfferWorker.setDept3name(deptName);
                        } else if (i == 3) {
                            tbOfferWorker.setDept4name(deptName);
                        }
                    }
                }
            }
            //民族
            String nation = tbOfferWorker.getNation();
            if (StringUtils.hasText(nation)) {
                String nationEnum = EnumUtil.getEnumValue("NEW_STAFF_ETHNICITY", nation);
                log.info("预备员工{}民族：{}{}", workerId, nationEnum, nation);
                tbOfferWorker.setNation(nationEnum);
            }
            //政治面貌
            String political = tbOfferWorker.getPoliticalLandscape();
            if (StringUtils.hasText(political)) {
                String politicalFormat = politicalFormat(political);
                String politics = EnumUtil.getEnumValue("NEW_STAFF_POLITICS", politicalFormat);
                log.info("预备员工{}政治面貌：{}{}", workerId, politics, politicalFormat);
                tbOfferWorker.setPoliticalLandscape(politics);
            }
            //性别
            String sex = tbOfferWorker.getSex();
            if (!StringUtils.hasText(sex)) {
                tbOfferWorker.setSex("男");
            }
            //籍贯
            String nationPlace = tbOfferWorker.getNationPlace();
            if (StringUtils.hasText(nationPlace)) {
                String nationPlaceValue = EnumUtil.getNationPlaceValue(nationPlace);
                log.info("预备员工{}籍贯{}{}", workerId, nationPlaceValue, nationPlace);
                tbOfferWorker.setNationPlace(nationPlaceValue);
            }
            tbOfferWorker.setDataSource("北森");
            //北森来的都是接受offer
            tbOfferWorker.setOfferStatus(OfferWorkerOfferStatusEnum.ACCEPT_OFFER);
            tbOfferWorker.setUpdateTime(new Date());
            tbOfferWorker.setUpdatorInfo("system/system");
            tbOfferWorkerMapper.insert(tbOfferWorker);
        }
    }

    /**
     * insert除附件外数据
     *
     * @param buildDTO
     */
    public void saveOfferData(BeiSenBuildDTO buildDTO) {
        //家庭信息
        List<OfferFamily> offerFamily = buildDTO.getTbOfferFamily();
        //紧急联系人
        OfferContactor offerContactor = buildDTO.getTbOfferContactor();
        //英语等级
        OfferLanguage offerLanguage = buildDTO.getTbOfferLanguage();
        //教育经历
        List<OfferStudy> offerStudy = buildDTO.getTbOfferStudy();
        //工作经历
        List<WorkerExperience> workerExperience = buildDTO.getTbWorkerExperience();
        //worker
        OfferWorker offerWorker = buildDTO.getTbOfferWorker();

        //再次更新 为了更新inType
        if (offerWorker != null) {
            TbOfferWorker tbOfferWorker = new TbOfferWorker();
            tbOfferWorker.setWorkerId(offerWorker.getWorkerId());
            tbOfferWorker.setInType(offerWorker.getInType());
            tbOfferWorkerMapper.updateById(tbOfferWorker);
        }

        if (offerLanguage != null) {
            TbOfferLanguage tbOfferLanguage = new TbOfferLanguage();
            CustomBeanUtils.copyProperties(offerLanguage, tbOfferLanguage);
            tbOfferLanguageMapper.insert(tbOfferLanguage);
        }
        if (offerContactor != null) {
            TbOfferContactor tbOfferContactor = new TbOfferContactor();
            CustomBeanUtils.copyProperties(offerContactor, tbOfferContactor);
            tbOfferContactorMapper.insert(tbOfferContactor);
        }
        if (!CollectionUtils.isEmpty(offerFamily)) {
            offerFamily.forEach(family -> {
                TbOfferFamily tbOfferFamily = new TbOfferFamily();
                CustomBeanUtils.copyProperties(family, tbOfferFamily);
                tbOfferFamilyMapper.insert(tbOfferFamily);
            });
        }
        if (!CollectionUtils.isEmpty(offerStudy)) {
            offerStudy.forEach(study -> {
                TbOfferStudy tbOfferStudy = new TbOfferStudy();
                CustomBeanUtils.copyProperties(study, tbOfferStudy);
                tbOfferStudyMapper.insert(tbOfferStudy);
            });
        }
        if (!CollectionUtils.isEmpty(workerExperience)) {
            workerExperience.forEach(exp -> {
                TbWorkerExperience tbWorkerExperience = new TbWorkerExperience();
                CustomBeanUtils.copyProperties(exp, tbWorkerExperience);
                if (StringUtils.hasText(tbWorkerExperience.getDepartment())) {
                    tbWorkerExperience.setDepartment(tbWorkerExperience.getDepartment().length() > 40 ? tbWorkerExperience.getDepartment().substring(0, 40) : tbWorkerExperience.getDepartment());
                }
                tbWorkerExperienceMapper.insert(tbWorkerExperience);
            });
        }
    }

    /**
     * offer接口中的数据
     */
    public Map<String, BiConsumer<BeiSenBuildDTO, Object>> offerMapForPropConsumer() {
        Map<String, BiConsumer<BeiSenBuildDTO, Object>> offerMap = new HashMap<>();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd");
        //北森系统中此员工编号
        offerMap.put("PersonID", (dto, val) -> dto.getTbOfferWorker().setBeiSenId(String.valueOf(val)));
        //姓名
        offerMap.put("Name", (dto, val) -> dto.getTbOfferWorker().setWorkerName(String.valueOf(val)));
        //新国籍 (国籍编码）
        offerMap.put("extNationality_105130_586467707", (dto, val) -> {
            dto.getTbOfferWorker().setNationalityCode(String.valueOf(val));
            dto.getTbOfferWorker().setNationality(commService.getCountry(String.valueOf(val)));
        });
        //国籍
        offerMap.put("extgj_105130_135771089", (dto, val) -> {
            if (!StringUtils.hasText(dto.getTbOfferWorker().getNationality())) {
                dto.getTbOfferWorker().setNationality(String.valueOf(val));
                if (!StringUtils.hasText(dto.getTbOfferWorker().getNationalityCode())) {
                    dto.getTbOfferWorker().setNationalityCode(commService.getCountry(String.valueOf(val)));
                }
            }
        });
        //证件类型
        offerMap.put("IDType", (dto, val) -> dto.getTbOfferWorker().setCertType(IdTypeEnum.getEnumByValue(String.valueOf(val))));
        //证件号码、出生日期（从身份证号中截取）
        offerMap.put("IDNumber", (dto, val) -> {
            String idCard = String.valueOf(val);
            dto.getTbOfferWorker().setCertNo(idCard);
            //出生日期，当身份证号异常是使用员工info接口中的Birthday字段
            if (StringUtils.hasText(idCard) && !StringUtils.containsWhitespace(idCard) && idCard.length() == 18) {
                try {
                    dto.getTbOfferWorker().setBirthday(sdf1.parse(idCard.substring(6, 10) + "-" + idCard.substring(10, 12) + "-" + idCard.substring(12, 14)));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        });
        //电话
        offerMap.put("Phone", (dto, val) -> dto.getTbOfferWorker().setPhoneNo(String.valueOf(val).trim()));
        //email
        offerMap.put("Email", (dto, val) -> dto.getTbOfferWorker().setEmail(String.valueOf(val)));
        //岗位
        offerMap.put("Post", (dto, val) -> {
            if (StringUtils.isEmpty(String.valueOf(val))) {
                throw new AppBusinessException("没有岗位信息");
            }
            dto.getTbOfferWorker().setPostId(String.valueOf(val).split("_")[2]);
            dto.getTbOfferWorker().setPostName(String.valueOf(val).split("_")[1]);
            dto.getTbOfferWorker().setPostInfo(String.valueOf(val));
        });
        //人事范围
        offerMap.put("extRSFW_105130_1272922788", (dto, val) -> {
            dto.getTbOfferWorker().setPersonnelRange(String.valueOf(val).substring(4));
            dto.getTbOfferWorker().setPersonnelRangeCode(String.valueOf(val).substring(0, 4));
        });
        //人事子范围
        offerMap.put("extrszfw_105130_859076654", (dto, val) -> {
            dto.getTbOfferWorker().setSubPersonnelRange(String.valueOf(val).substring(4));
            dto.getTbOfferWorker().setSubPersonnelRangeCode(String.valueOf(val).substring(0, 4));
        });
        //起薪建议 tips 调用SAP生成预备工号需要薪资信息 不存本地数据库
        offerMap.put("AfterBasicPay", (dto, val) -> dto.getTbOfferWorker().setBasicSalary(new BigDecimal(String.valueOf(val))));
        //新工作履行地
        offerMap.put("extSAPWorkPlace_105130_1432849287", (dto, val) -> {
            if (!"CN".equals(String.valueOf(val))) {
                dto.getTbOfferWorker().setNewWorkCityCode(String.valueOf(val));
            }
        });
        //工作履行地
        offerMap.put("extgzlxd_105130_1655288965", (dto, val) -> {
            if (!StringUtils.hasText(dto.getTbOfferWorker().getWorkCity())) {
                dto.getTbOfferWorker().setWorkCity(String.valueOf(val));
            }
        });
        //外派工作地
        offerMap.put("extwpgzd_105130_2136785323", (dto, val) -> dto.getTbOfferWorker().setOuterCity(String.valueOf(val)));
        //目标奖金比例 tips 调用SAP生成预备工号需要薪资信息 不存本地数据库
        offerMap.put("extmbjjbl_105130_269735149", (dto, val) -> dto.getTbOfferWorker().setTargetBonusPercent(new BigDecimal(String.valueOf(val))));
        //职级等级
        offerMap.put("extzj_105130_2056502811", (dto, val) -> dto.getTbOfferWorker().setJobLevel(String.valueOf(val)));
        //职级职类
        offerMap.put("extzl_105130_632469901", (dto, val) -> dto.getTbOfferWorker().setJobGrade(String.valueOf(val)));
        //offer类型 校招Offer  01：  ebe9f4b9-3b3b-4d7b-a2c0-799a5996c2d4  社招Offer 02：  ecdac8d2-1888-42bb-95d0-f18c1a94e90f   实习offer 03：3d91fad5-3bd1-4d75-9ec2-87810307512c
        offerMap.put("OfferTypeID", (dto, val) -> {
            String offerType = "";
            String inType = "";
            switch (String.valueOf(val)) {
                case "ebe9f4b9-3b3b-4d7b-a2c0-799a5996c2d4":
                    offerType = "01";
                    inType = "应届毕业生(校招)";
                    break;
                case "ecdac8d2-1888-42bb-95d0-f18c1a94e90f":
                    offerType = "02";
                    inType = "社会招聘";
                    break;
                case "3d91fad5-3bd1-4d75-9ec2-87810307512c":
                    offerType = "03";
                    inType = "实习";
                    break;
                default:
                    break;
            }
            dto.getTbOfferWorker().setOfferTypeId(offerType);
            dto.getTbOfferWorker().setInType(inType);
        });
        //预计报到日期， 对于校招和社招他们报到日期是两个字段
        //校招↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        offerMap.put("PlanTime", (dto, val) -> {
            try {
                dto.getTbOfferWorker().setPlanReportDate(sdf2.parse(String.valueOf(val)));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
        //校招↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        //社招↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        offerMap.put("extyjbdrq_105130_1048690029", (dto, val) -> {
            try {
                dto.getTbOfferWorker().setPlanReportDate(sdf2.parse(String.valueOf(val)));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
        //是否高才岗位
        offerMap.put("extshifougaocaigangwei_105130_1946596464", (dto, val) -> dto.getTbOfferWorker().setHignTalentPostFlag(("1".equals(String.valueOf(val)) || "是".equals(String.valueOf(val))) ? "1" : "2"));
        //是否国际化人才
        offerMap.put("extshifouguojihua_105130_1704552922", (dto, val) -> dto.getTbOfferWorker().setInternationalTalentFlag(("1".equals(String.valueOf(val)) || "是".equals(String.valueOf(val))) ? "1" : "2"));
        //是否项目性社招岗位 tips 数据库没有字段 不存本地数据库
        offerMap.put("extshifouxiangmuxingshezhao_105130_1255800761", (dto, val) -> dto.getTbOfferWorker().setProjectBasedSocialRecruitFlag(("1".equals(String.valueOf(val)) || "是".equals(String.valueOf(val))) ? "1" : "2"));
        //是否特批
        offerMap.put("extsftsp_105130_899255513", (dto, val) -> dto.getTbOfferWorker().setSpecialApprovalFlag(("1".equals(String.valueOf(val)) || "是".equals(String.valueOf(val))) ? "1" : "2"));
        //是否需签署竞业协议
        offerMap.put("extXH30708_105130_173826491", (dto, val) -> dto.getTbOfferWorker().setNeedSignCompetition(("1".equals(String.valueOf(val)) || "是".equals(String.valueOf(val))) ? "1" : "2"));
        //月项目津贴 tips 调用SAP生成预备工号需要薪资信息 不存本地数据库
        offerMap.put("extyxmjt_105130_412173415", (dto, val) -> dto.getTbOfferWorker().setMonthlyProjectAllowance(new BigDecimal(String.valueOf(val))));
        //目标及奖金金额（项目制）tips 调用SAP生成预备工号需要薪资信息 不存本地数据库
        offerMap.put("extmbjjjexm_105130_1286130174", (dto, val) -> dto.getTbOfferWorker().setTargetAndBonusAmount(new BigDecimal(String.valueOf(val))));
        //是否项目制员工
        offerMap.put("extsptx_105130_328262957", (dto, val) -> dto.getTbOfferWorker().setProjectWorkerFlag("项目制招聘".equals(String.valueOf(val)) ? "1" : "2"));
        //招聘项目名称
        offerMap.put("extxiangmumingcheng_105130_1961129030", (dto, val) -> dto.getTbOfferWorker().setOfferProjectName(String.valueOf(val)));
        //特批类型
        offerMap.put("extspyy_105130_1378947848", (dto, val) -> dto.getTbOfferWorker().setSpecialApprovalType(String.valueOf(val)));
        //特批说明
        offerMap.put("extqita_105130_191577148", (dto, val) -> dto.getTbOfferWorker().setSpecialApprovalNote(String.valueOf(val)));
        //社招↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

        return offerMap;
    }

    /**
     * info接口中数据
     */
    public Map<String, BiConsumer<BeiSenBuildDTO, Object>> infoMapForPropConsumer() {
        Map<String, BiConsumer<BeiSenBuildDTO, Object>> infoMap = new HashMap<>();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd");
        //预备员工号  如果存在则进行数据库信息更新，不再创建预备工号，没有则正常创建预备工号
        infoMap.put("extybygbh_105130_1881359711", (dto, val) -> dto.getTbOfferWorker().setWorkerId(String.valueOf(val)));
        //性别
        infoMap.put("gender", (dto, val) -> dto.getTbOfferWorker().setSex(String.valueOf(val)));
        //民族
        infoMap.put("Nation", (dto, val) -> dto.getTbOfferWorker().setNation(String.valueOf(val)));
        //籍贯
        infoMap.put("NativePlace", (dto, val) -> dto.getTbOfferWorker().setNationPlace(String.valueOf(val)));
        //政治面貌
        infoMap.put("polity", (dto, val) -> dto.getTbOfferWorker().setPoliticalLandscape(String.valueOf(val)));
        //手机
        infoMap.put("Mobile", (dto, val) -> dto.getTbOfferWorker().setPhoneNo(String.valueOf(val)));
        //生日
        infoMap.put("Birthday", (dto, val) -> {
            Date birthday = dto.getTbOfferWorker().getBirthday();
            if (birthday == null) {
                try {
                    dto.getTbOfferWorker().setBirthday(sdf1.parse(String.valueOf(val)));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        });
        //地址
        infoMap.put("Address", (dto, val) -> dto.getTbOfferWorker().setContactAddress(String.valueOf(val)));
        //婚否
        infoMap.put("WedState", (dto, val) -> dto.getTbOfferWorker().setSpouseFlag("已婚".equals(String.valueOf(val)) ? "1" : "0"));
        //旧工号
        infoMap.put("extH3Ccode_105130_1742053515", (dto, val) -> dto.getTbOfferWorker().setOldWorkerId(String.valueOf(val)));
        //身份证证件
        infoMap.put("extsfz_105130_143450722", (dto, val) -> dto.getTbOfferWorker().setIdCardPics(String.valueOf(val)));
        //利益冲突证明
        infoMap.put("extlyctsm_105130_1067091392", (dto, val) -> dto.getTbOfferWorker().setInterestConflictPic(String.valueOf(val)));
        //学历学位验证信息截图
        infoMap.put("extyanzheng_105130_1234694363", (dto, val) -> dto.getTbOfferWorker().setAcademicDegreeVerifyPics(String.valueOf(val)));
        //学历证
        infoMap.put("extxuelizm_105130_1716870131", (dto, val) -> dto.getTbOfferWorker().setAcademicPic(String.valueOf(val)));
        //学位证
        infoMap.put("extxueweizm_105130_1077205403", (dto, val) -> dto.getTbOfferWorker().setDegreePic(String.valueOf(val)));
        //银行流水截图
        infoMap.put("extyhls_105130_1124409346", (dto, val) -> dto.getTbOfferWorker().setBankFlowPic(String.valueOf(val)));
        //紧急联系人姓名
        infoMap.put("EmergencyContact", (dto, val) -> dto.getTbOfferWorker().setEmergencyContactor(String.valueOf(val)));
        //紧急联系人电话
        infoMap.put("EmergencyPhone", (dto, val) -> dto.getTbOfferWorker().setEmergencyPhone(String.valueOf(val)));
        //英语能力  未参加 四级 六级
        infoMap.put("ExamCategory", (dto, val) -> dto.getTbOfferWorker().setEnglishLevel(String.valueOf(val)));
        //英语水平证明
        infoMap.put("extywzm_105130_2061911719", (dto, val) -> dto.getTbOfferWorker().setEnglishLevelPic(String.valueOf(val)));
        //云数择优,标签中包含670cbded-5d52-4fa8-9462-f51ca2906868表示是云数择优，试用期设为6个月
        infoMap.put("R_LabelIds", (dto, val) -> {
            String value = String.valueOf(val);
            if (!StringUtils.isEmpty(value) && value.contains("670cbded-5d52-4fa8-9462-f51ca2906868")) {
                dto.getTbOfferWorker().setProbationMonth(6);
            }
        });
        return infoMap;
    }

    /**
     * 组装工作经历、教育背景、家庭信息、紧急联系人、英语等级
     *
     * @param buildDTO
     * @param infoDTO
     */
    public void fillOtherInfo(BeiSenBuildDTO buildDTO, BeiSenInfoDTO infoDTO) {
        OfferWorker offerWorker = buildDTO.getTbOfferWorker();
        //预备员工号
        String workerId = offerWorker.getWorkerId();
        SimpleDateFormat sdf = new SimpleDateFormat("y-M-d");
        Date createTime = new Date();
        //工作经历
        BeiSenInfoDTO.BeiSenWorkExperience workExperience = infoDTO.getWorkExperience();
        List<BeiSenInfoDTO.WorkExperienceItems> workItems = workExperience.getItems();
        if (!CollectionUtils.isEmpty(workItems)) {
            List<WorkerExperience> experienceList = new ArrayList<>();
            workItems.forEach(item -> {
                WorkerExperience exp = new WorkerExperience();
                exp.setExperienceId(IdWorker.nextId() + "");
                exp.setWorkerId(workerId);
                exp.setWorkPlace(item.getCompanyName());
                try {
                    if (StringUtils.hasText(item.getStartTime())) {
                        exp.setBeginDate(sdf.parse(item.getStartTime()));
                    }
                    if (StringUtils.hasText(item.getEndTime())) {
                        if ("至今".equals(item.getEndTime())) {
                            exp.setEndDate(new Date());
                        } else {
                            exp.setEndDate(sdf.parse(item.getEndTime()));
                        }
                    }
                } catch (Exception e) {
                    log.error("工作经历起止日期转换异常，预备工号：" + workerId);
                    e.printStackTrace();
                }
                exp.setDepartment(item.getDepartment());
                exp.setPost(item.getJobTitle());
                //1为从北森同步过来的数据无法更改 2为本地输入数据可以修改
                exp.setType("1");
                exp.setLeaveReason(item.getReasonOfLeaving());
                exp.setReferenceName(item.getReferenceName());
                exp.setReferenceNameContact(item.getReferenceLinkInfo());
                exp.setUpdateTime(createTime);
                exp.setAlreadySave(false);
                //经历类型  0非工作经历    1工作经历
                exp.setExperienceType(1);
                exp.setIsBeisenData(true);
                experienceList.add(exp);
            });
            buildDTO.setTbWorkerExperience(experienceList);
        } else {
            String offerTypeId = offerWorker.getOfferTypeId();
            String inType = offerWorker.getInType();
            //社会招聘的没有工作经历的人 算作应届毕业生
            if ((StringUtils.hasText(offerTypeId) && offerTypeId.equals("02")) || (StringUtils.hasText(inType) && inType.equals("社会招聘"))) {
                offerWorker.setInType("应届毕业生(社招)");
            }
        }

        //教育背景
        BeiSenInfoDTO.BeiSenEducationExperience eduExperience = infoDTO.getEducationExperience();
        List<BeiSenInfoDTO.EducationExperienceItems> eduItems = eduExperience.getItems();
        if (!CollectionUtils.isEmpty(eduItems)) {
            List<OfferStudy> eduList = new ArrayList<>();
            eduItems.forEach(item -> {
                OfferStudy edu = new OfferStudy();
                String studyId = IdWorker.nextId() + "";
                edu.setStudyId(studyId);
                edu.setWorkerId(workerId);
                edu.setCollegeName(item.getSchoolName());
                edu.setMajorName(item.getMajorName());
                try {
                    if (StringUtils.hasText(item.getStartTime())) {
                        edu.setBeginDate(sdf.parse(item.getStartTime()));
                    }
                    if (StringUtils.hasText(item.getEndTime()) && !"至今".equals(item.getEndTime())) {
                        edu.setEndDate(sdf.parse(item.getEndTime()));
                    }
                } catch (Exception e) {
                    log.error("教育经历起止日期转换异常，预备工号：" + workerId);
                    e.printStackTrace();
                }
                List<BeiSenInfoDTO.BeiSenItems> customFields = item.getCustomFields();
                //学历学位证图片
                if (!CollectionUtils.isEmpty(customFields)) {
                    customFields.forEach(field -> {
                        String url = field.getValue();
                        if (StringUtils.hasText(url)) {
                            if ("extbiyezheng_105130_1092640093".equals(field.getPropertyName())) {
                                Map<String, String> map = uploadEducationFiles(url, TbOfferAttachment.ACADEMIC, studyId);
                                edu.setEducationFileId(map.get("fileId"));
                                edu.setEducationFileName(map.get("fileName"));
                            } else if ("extxueweizheng_105130_881727390".equals(field.getPropertyName())) {
                                Map<String, String> map = uploadEducationFiles(url, TbOfferAttachment.DEGREE, studyId);
                                edu.setDegreeFileId(map.get("fileId"));
                                edu.setDegreeFileName(map.get("fileName"));
                            }
                        }
                    });
                }
                edu.setStudyType(StudyTypeEnum.getEnumByBeiSenName(item.getFormsOfLearning().getExtendValue()));
                String eduEnumName = educationFormat(item.getEducationLevel().getExtendValue(), StudyTypeEnum.FULL_TIME.equals(StudyTypeEnum.getEnumByBeiSenName(item.getFormsOfLearning().getExtendValue())));
                edu.setEducation(EducationLevelEnum.getEnumByName(eduEnumName));
                edu.setDegree(degreeFormat(item.getDegree().getExtendValue()));
                //1为从北森同步过来的数据无法更改 2为本地输入数据可以修改
                edu.setType("1");
                edu.setUpdateTime(createTime);
                edu.setAlreadySave(false);
                edu.setIsBeisenData(true);
                eduList.add(edu);
            });
            buildDTO.setTbOfferStudy(eduList);
        }

        //家庭信息
        BeiSenInfoDTO.BeiSenFamilyList family = infoDTO.getFamilyList();
        List<BeiSenInfoDTO.FamilyItems> familyItems = family.getItems();
        if (!CollectionUtils.isEmpty(familyItems)) {
            List<OfferFamily> familyList = new ArrayList<>();
            familyItems.forEach(item -> {
                if (StringUtils.hasText(item.getRelation()) && !"配偶".equals(item.getRelation())) {
                    OfferFamily fam = new OfferFamily();
                    fam.setFamilyId(IdWorker.nextId() + "");
                    fam.setWorkerId(workerId);
                    fam.setRelationType(relationFormat(item.getRelation()));
                    fam.setMemberName(item.getName());
                    fam.setMemberAddress(item.getFamilyLocaltion());
                    fam.setWorkPlace(item.getWorkPlace());
                    fam.setMemberPhone(item.getTelephone());
                    fam.setUpdateTime(createTime);
                    fam.setAlreadySave(false);
                    familyList.add(fam);
                }
            });
            buildDTO.setTbOfferFamily(familyList);
        }

        //紧急联系人
        if (StringUtils.hasText(offerWorker.getEmergencyContactor())) {
            OfferContactor contactor = new OfferContactor();
            contactor.setContactorId(IdWorker.nextId() + "");
            contactor.setWorkerId(workerId);
            contactor.setContactorName(offerWorker.getEmergencyContactor());
            contactor.setContactorPhone(offerWorker.getEmergencyPhone());
            contactor.setUpdateTime(createTime);
            contactor.setAlreadySave(false);
            buildDTO.setTbOfferContactor(contactor);
        }

        //英语等级
        if (StringUtils.hasText(offerWorker.getEnglishLevel())) {
            OfferLanguage language = new OfferLanguage();
            language.setLanguageId(IdWorker.nextId() + "");
            language.setWorkerId(workerId);
            language.setLanguageType("英语");
            language.setQualification(offerWorker.getEnglishLevel());
            language.setEngMark("1");
            language.setUpdateTime(createTime);
            buildDTO.setTbOfferLanguage(language);
        }

    }

    public String relationFormat(String oriRela) {
        switch (oriRela) {
            case "丈夫":
                return "01";
            case "妻子":
                return "02";
            case "父亲":
                return "05";
            case "母亲":
                return "06";
            case "姐姐":
                return "11";
            case "妹妹":
                return "12";
            case "哥哥":
                return "13";
            case "弟弟":
                return "14";
            default:
                return "";
        }
    }

    /**
     * 北森学位转SAP学位
     *
     * @param beiSenName
     * @return
     */
    public DegreeLevelEnum degreeFormat(String beiSenName) {
        if ("无".equals(beiSenName)) {
            return DegreeLevelEnum.NO_DEGREE;
        } else if ("学士".equals(beiSenName)) {
            return DegreeLevelEnum.BACHELORS_DEGREE;
        } else if ("双学士".equals(beiSenName)) {
            return DegreeLevelEnum.DUAL_DEGREE;
        } else if ("硕士".equals(beiSenName)) {
            return DegreeLevelEnum.PHD;
        } else if ("MBA".equals(beiSenName)) {
            return DegreeLevelEnum.MBA_DEGREE;
        } else if ("博士".equals(beiSenName)) {
            return DegreeLevelEnum.MASTER_DEGREE;
        }
        throw new AppBusinessException("未找到对应DegreeLevelEnum枚举：" + beiSenName);
    }

    public String politicalFormat(String politicalName) {
        if ("中共党员".equals(politicalName)) {
            return "中国共产党党员";
        } else if ("共青团员".equals(politicalName)) {
            return "中国共青团团员";
        } else if ("中共预备党员".equals(politicalName)) {
            return "中国共产党预备党员";
        }
        return politicalName;
    }

    /**
     * 北森学历转SAP学历
     *
     * @param beiSenName
     * @param isFullTime
     * @return
     */
    public String educationFormat(String beiSenName, boolean isFullTime) {
        if (!StringUtils.hasText(beiSenName)) {
            return null;
        }
        //全日制
        if (isFullTime) {
            if (beiSenName.contains("硕士研究生")) {
                return EducationLevelEnum.MASTER.getTypeName();
            } else if (beiSenName.contains("中技")) {
                return EducationLevelEnum.TECHNICAL.getTypeName();
            } else if (beiSenName.contains("博士研究生")) {
                return EducationLevelEnum.PHD.getTypeName();
            }
        } else {
            //非全
            if (beiSenName.contains("大专")) {
                return EducationLevelEnum.COLLEGE_OTH.getTypeName();
            } else if (beiSenName.contains("本科")) {
                return EducationLevelEnum.UNDERGRADUATE_OTH.getTypeName();
            } else if (beiSenName.contains("硕士研究生")) {
                return EducationLevelEnum.MASTER_OTH.getTypeName();
            } else if (beiSenName.contains("博士研究生")) {
                return EducationLevelEnum.PHD_OTH.getTypeName();
            }
        }
        return beiSenName;
    }

    /**
     * 调用SAP更新预备员工信息
     *
     * @param buildDTO
     */
    @SneakyThrows
    public Map<String, String> callSapForUpdatePreWorker(BeiSenBuildDTO buildDTO) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        OfferWorker worker = buildDTO.getTbOfferWorker();
        //获取SAP客户端
        rfcManager.connect();
        JCoDestination destination = rfcManager.getDestination();
        //调用SAP接口
        JCoFunction func = rfcManager.getFunction(destination, "ZFM_HR_MOD_YBYG");
        //组装SAP入参
        JCoParameterList input = func.getImportParameterList();
        JCoParameterList table = func.getTableParameterList();
        log.info("组装更新预备员工信息 SAP入参================================================================================");
        input.setValue("I_PERNR", worker.getWorkerId());
        JCoTable itField = table.getTable("IT_FIELD");
        //职位ID
        itField.appendRow();
        itField.setValue("ZZNAME", "PLANS");
//        itField.setValue("ZZVALUE", "50002895");//测试使用 todo
        itField.setValue("ZZVALUE",  worker.getPostInfo().substring(worker.getPostInfo().length() - 8));
        log.info("PLANS岗位编码={}", worker.getPostInfo().substring(worker.getPostInfo().length() - 8));
        //人事范围ID
        itField.appendRow();
        itField.setValue("ZZNAME", "WERKS");
//        itField.setValue("ZZVALUE", "H014");    //测试使用 todo
        itField.setValue("ZZVALUE", worker.getPersonnelRangeCode());
        log.info("WERKS人事范围编码={}", worker.getPersonnelRangeCode());
        //人事子范围ID
        itField.appendRow();
        itField.setValue("ZZNAME", "BTRTL");
//        itField.setValue("ZZVALUE", "C014");        //测试使用 todo
        itField.setValue("ZZVALUE", worker.getSubPersonnelRangeCode());
        log.info("BTRTL人事子范围编码={}", worker.getSubPersonnelRangeCode());
        //计划入职日期
        if (worker.getPlanReportDate() != null) {
            itField.appendRow();
            itField.setValue("ZZNAME", "ZDATE");
            itField.setValue("ZZVALUE", sdf.format(worker.getPlanReportDate()));
            log.info("ZDATE拟入职日期={}", sdf.format(worker.getPlanReportDate()));
        }
        //工作履行地ID
        String workCityCode = worker.getNewWorkCityCode();//北森新字段  工作履行地编码
        if (!StringUtils.hasText(workCityCode)) {
            workCityCode = EnumUtil.getEnumValue("NEW_STAFF_WORKPLACECODES", worker.getWorkCity());
        }
        if (StringUtils.hasText(workCityCode)) {
            itField.appendRow();
            itField.setValue("ZZNAME", "ZOFFICE5");
            itField.setValue("ZZVALUE", workCityCode);
            log.info("ZOFFICE5工作履行地={}", workCityCode);
        }
        //外派工作地ID
        String outerCityCode = EnumUtil.getEnumValue("NEW_STAFF_OUTPUTTINGCODES", worker.getOuterCity());
        if (StringUtils.hasText(outerCityCode)) {
            itField.appendRow();
            itField.setValue("ZZNAME", "ZOFFICE6");
            itField.setValue("ZZVALUE", outerCityCode);
            log.info("ZOFFICE6外派工作地={}", outerCityCode);
        }

        log.info("组装更新预备员工信息 SAP入参完毕================================================================================");

        func.execute(destination);
        JCoParameterList exportParameterList = func.getExportParameterList();

        //返回消息类型
        //S	成功
        //I	信息
        //A	取消
        //E	错误
        //W	警告
        String type = exportParameterList.getString("E_MSGTY");
        String deptId = exportParameterList.getStructure("E_ORGEH").getString("ORGEH");
        log.info("E_MSGTY消息类型={}", type);

        //消息文本
        String msg = exportParameterList.getString("E_MSGTX");
        log.info("E_MSGTX消息内容={}", msg);

        sdRequestRecordService.addReqRecord(worker.getWorkerId(), RequestEnum.更新预备员工.getName(), RequestEnum.更新预备员工.getUrl(), itField.toXML(), exportParameterList.toXML());

        Map<String, String> retMap = new HashMap<>();
        if (!type.equals("S")) {
            retMap.put("msg", msg);
        }
        retMap.put("directDeptId", deptId);
        return retMap;
    }

    /**
     * 调用SAP生成预备工号
     */
    @SneakyThrows
    public Map<String, String> callSapForPreWorkerNumber(BeiSenBuildDTO buildDTO) {
        Map<String, String> retMap = new HashMap<>();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        OfferWorker worker = buildDTO.getTbOfferWorker();
        //获取SAP客户端
        rfcManager.connect();
        JCoDestination destination = rfcManager.getDestination();

        //调用SAP接口
        JCoFunction func = rfcManager.getFunction(destination, "ZRFC_XRYBYG_CREATE");
        //组装SAP入参
        JCoParameterList paramObj = func.getImportParameterList();
        JCoStructure table = paramObj.getStructure("LW_DATA");
        log.info("组装生成预备工号 SAP入参================================================================================");
        //姓名
        table.setValue("NACHN", worker.getWorkerName());
        log.info("NACHN姓名={}", worker.getWorkerName());
        //性别 1-男 2-女
        if (StringUtils.hasText(worker.getSex())) {
            table.setValue("GESCH", worker.getSex().equals("男") ? "1" : "2");
            log.info("GESCH性别={}", worker.getSex().equals("男") ? "1" : "2");
        }
        //出生日期 要求格式：yyyyMMdd
        try {
            sdf.format(worker.getBirthday());
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
            retMap.put("msg", "出生日期数据异常");
            return retMap;
        }
        table.setValue("GBDAT", sdf.format(worker.getBirthday()));
        log.info("GBDAT出生日期={}", sdf.format(worker.getBirthday()));
        //国籍 国家的SAP编码
        table.setValue("NATIO", StringUtils.hasText(worker.getNationalityCode()) ? worker.getNationalityCode() : commService.getCountry(worker.getNationality()));
        log.info("NATIO国籍={}", StringUtils.hasText(worker.getNationalityCode()) ? worker.getNationalityCode() : commService.getCountry(worker.getNationality()));
        //证件类型
        if (worker.getCertType() == null) {
            retMap.put("msg", "证件类型为空");
            return  retMap;
        }
        table.setValue("ICTYP", worker.getCertType().getSapValue());
        log.info("ICTYP证件类型={}", worker.getCertType().getSapValue());
        //证件号码
        if (!StringUtils.hasText(worker.getCertNo())) {
            retMap.put("msg", "证件号码为空");
            return retMap;
        }
        table.setValue("ICNUM", worker.getCertNo());
        log.info("ICNUM证件号码={}", worker.getCertNo());
        //岗位编码
//        table.setValue("PLANS", "50002895");//测试使用 todo
        table.setValue("PLANS", worker.getPostInfo().substring(worker.getPostInfo().length() - 8));
        log.info("PLANS岗位编码={}", worker.getPostInfo().substring(worker.getPostInfo().length() - 8));
        //旧工号
        table.setValue("ZNUMR2", worker.getOldWorkerId());
        log.info("ZNUMR2旧工号={}", worker.getOldWorkerId());
        //人事范围编码    人事范围sap编码
//        table.setValue("WERKS", "H014");//测试使用 todo
        table.setValue("WERKS", worker.getPersonnelRangeCode());
        log.info("WERKS人事范围编码={}", worker.getPersonnelRangeCode());
        //人事子范围编码   人事子范围sap编码
//        table.setValue("BTRTL", "C014");//测试使用 todo
        table.setValue("BTRTL", worker.getSubPersonnelRangeCode());
        log.info("BTRTL人事子范围编码={}", worker.getSubPersonnelRangeCode());
        //工作履行地 工作履行地sap编码
        String workCityCode = worker.getNewWorkCityCode();//北森新字段  工作履行地编码
        if (!StringUtils.hasText(workCityCode)) {
            workCityCode = EnumUtil.getEnumValue("NEW_STAFF_WORKPLACECODES", worker.getWorkCity());
        }
        if (!StringUtils.hasText(workCityCode)) {
            retMap.put("msg", "工作履行地枚举获取异常");
            return retMap;
        }
        table.setValue("ZOFFICE7", workCityCode);
        log.info("ZOFFICE7工作履行地={}", workCityCode);
        //外派工作地 外派工作地sap编码
        String outerCityCode = EnumUtil.getEnumValue("NEW_STAFF_OUTPUTTINGCODES", worker.getOuterCity());
        table.setValue("ZOFFICE6", outerCityCode);
        log.info("ZOFFICE6外派工作地={}", outerCityCode);
        //起薪建议
        table.setValue("BETXX", worker.getBasicSalary() == null ? new BigDecimal("0") : worker.getBasicSalary());
//        log.info("BETXX起薪建议={}", worker.getBasicSalary());
        //目标奖金比例
        table.setValue("BNRTE", worker.getTargetBonusPercent() == null ? new BigDecimal("0") : worker.getTargetBonusPercent().multiply(new BigDecimal("100")));
//        log.info("BNRTE目标奖金比例={}", worker.getTargetBonusPercent());
        //货币码   目前写死 RMB
        table.setValue("WAERS", "RMB");
        log.info("WAERS货币码={}", "RMB");
        //数字职级
        table.setValue("ZHRDJ", worker.getJobLevel());
        log.info("ZHRDJ数字职级={}", worker.getJobLevel());
        //职级等级
        table.setValue("ZHRGL", worker.getJobGrade());
        log.info("ZHRGL职级等级={}", worker.getJobGrade());
        //ZHRGL + ZHRDJ
        table.setValue("PSLVL",  worker.getJobGrade() + worker.getJobLevel());
        log.info("PSLVL={}", worker.getJobGrade() +  worker.getJobLevel());
        //拟入职日期 要求格式：yyyyMMdd
        if (worker.getPlanReportDate() != null) {
            table.setValue("ZYRZRQ", sdf.format(worker.getPlanReportDate()));
            log.info("ZYRZRQ拟入职日期={}", sdf.format(worker.getPlanReportDate()));
        }
        //offer类型
        table.setValue("MASSG", worker.getOfferTypeId());
        log.info("MASSG offer类型={}", worker.getOfferTypeId());
        //手机号码
        table.setValue("TELNR", worker.getPhoneNo());
        log.info("TELNR手机号码={}", worker.getPhoneNo());
        //当前时间
        table.setValue("ZDATE", sdf.format(new Date()));
        log.info("ZDATE当前时间={}", sdf.format(new Date()));
        //是否高才岗位
        table.setValue("ZGCGW", worker.getHignTalentPostFlag());
        log.info("ZGCGW是否高才岗位={}", worker.getHignTalentPostFlag());
        //是否国际化人才
        table.setValue("ZGJHRC", worker.getInternationalTalentFlag());
        log.info("ZGJHRC是否国际化人才={}", worker.getInternationalTalentFlag());
        //是否项目性质社招
        table.setValue("ZXMSZ", worker.getProjectBasedSocialRecruitFlag());
        log.info("ZXMSZ是否项目性质社招={}", worker.getProjectBasedSocialRecruitFlag());
        //招聘项目名称
        table.setValue("ZZPMC", worker.getOfferProjectName());
        log.info("ZZPMC招聘项目名称={}", worker.getOfferProjectName());
        //是否特批
        table.setValue("ZTPF", worker.getSpecialApprovalFlag());
        log.info("ZTPF是否特批={}", worker.getSpecialApprovalFlag());
        //特批类型
        table.setValue("ZTPLX", worker.getSpecialApprovalType());
        log.info("ZTPLX特批类型={}", worker.getSpecialApprovalType());
        //特批说明
        table.setValue("ZTPSM", worker.getSpecialApprovalNote());
        log.info("ZTPSM特批说明={}", worker.getSpecialApprovalNote());
        //是否需要签署竞业协议
        table.setValue("ZJYXYF", worker.getNeedSignCompetition());
        log.info("ZJYXYF是否需要签署竞业协议={}", worker.getNeedSignCompetition());
        //A月项目津贴 为空时，传0
        table.setValue("BYXMJT", worker.getMonthlyProjectAllowance() == null ? new BigDecimal("0") : worker.getMonthlyProjectAllowance());
//        log.info("BYXMJT A月项目津贴={}", worker.getMonthlyProjectAllowance() == null ? new BigDecimal("0") : worker.getMonthlyProjectAllowance());
        //目标及奖金金额（项目制） 为空时，传0
        table.setValue("BYXMJJ", worker.getTargetAndBonusAmount() == null ? new BigDecimal("0") : worker.getTargetAndBonusAmount());
//        log.info("BYXMJJ目标及奖金金额（项目制）={}", worker.getTargetAndBonusAmount() == null ? new BigDecimal("0") : worker.getTargetAndBonusAmount());
        //是否项目制员工
        table.setValue("ZXMZ", worker.getProjectWorkerFlag());
        log.info("ZXMZ是否项目制员工={}", worker.getProjectWorkerFlag());
        log.info("组装生成预备工号 SAP入参完毕================================================================================");

        func.execute(destination);
        JCoParameterList exportParameterList = func.getExportParameterList();

        //SAP生成的预备工号    执行异常时，返回00000000
        String generatePreId = exportParameterList.getString("PERNR");
        log.info("PERNR预备工号={}", generatePreId);
        //描述文本
        String msg = exportParameterList.getString("ZMSG");
        log.info("ZMSG描述文本={}", msg);
        //预备员工所属最小部门ID
        String directDeptId = exportParameterList.getString("O_ORGEH");
        log.info("O_ORGEH直属部门={}", directDeptId);
        //处理结果  S-成功    E-异常
        String resCode = exportParameterList.getString("ZMSGTY");
        log.info("ZMSGTY处理结果={}", resCode);

        //记录接口参数，薪资脱敏
        table.setValue("BETXX", new BigDecimal("0"));
        table.setValue("BNRTE", new BigDecimal("0"));
        table.setValue("BYXMJT", new BigDecimal("0"));
        table.setValue("BYXMJJ", new BigDecimal("0"));
        sdRequestRecordService.addReqRecord(worker.getWorkerId(), RequestEnum.生成预备工号.getName(), RequestEnum.生成预备工号.getUrl(), table.toXML(), exportParameterList.toXML());

        if (resCode.equals("S")) {
//            retMap.put("directDeptId", "50045117"); // 测试使用 todo
            retMap.put("directDeptId", directDeptId);
            retMap.put("preId", generatePreId);
        } else {
            retMap.put("msg", msg);
        }
        return retMap;
    }

    /**
     * sap生成预备工号异常 给职位发布人发送邮件（可能有多位，抄送给管理员）
     *
     * @param infoDTO
     * @param name
     * @param errorMsg
     * @param beiSenNumber
     * @param certNo
     */
    public void sendExceptionMsg(BeiSenInfoDTO infoDTO, String name, String errorMsg, String beiSenNumber, String certNo) {
        StringBuilder noticeEmailSb = new StringBuilder();
        StringBuilder noticeNameSb = new StringBuilder(" ");
        List<BeiSenInfoDTO.BeiSenApplyJobSummaries> applyJobSummaries = infoDTO.getApplyJobSummaries();
        if (!CollectionUtils.isEmpty(applyJobSummaries)) {
            applyJobSummaries.forEach(job -> {
                if (job.getApplyInfo() != null
                        && job.getApplyInfo().getStatusInfo() != null
                        && job.getApplyInfo().getPhaseInfo() != null
                        && "S027".equals(job.getApplyInfo().getPhaseInfo().getCode())
                        && "U02".equals(job.getApplyInfo().getStatusInfo().getCode())) {
                    noticeNameSb.append(job.getDutyUserName()).append(",");
                    noticeEmailSb.append(job.getDutyUserEmail()).append(",");
                }
            });
        }
        SdNoticeRecord noticeRecord = new SdNoticeRecord();
        noticeRecord.setNoticeId(IdWorker.nextId() + "");
        noticeRecord.setFlowId("-1");
        noticeRecord.setNoticeType(BusiEnumDefine.NOTICE_TYPE_EMAIL);
        noticeRecord.setTargetEmail(noticeEmailSb.toString());
        noticeRecord.setCopyToEmail(sapNoticeMail);
        noticeRecord.setNoticeTitle("北森数据写入SAP预备员工失败");
        noticeRecord.setNoticeContent(noticeNameSb.substring(0, noticeNameSb.length() - 1) + "您好：<br>由于北森ID：" + beiSenNumber +
                " 姓名：" + name +
                " 证件号：" + certNo +
                " 因 " + errorMsg + " 无法写入SAP生成预备员工号。<br>" +
                "建议检查国籍和身份证的填写情况和:" + errorMsg +
                "<br>请您及时处理北森数据，保证后续环节顺利流转。");
        noticeRecord.setCreateTime(new Date());
        asyncSendMessage.sendMessage(Collections.singletonList(noticeRecord));
    }

    /**
     * 发邮件或短信给预备员工
     *
     * @param templateCode
     * @param workerName
     * @param email
     * @param phone
     * @param account
     * @param password
     */
    public void sendNoticeToWorker(String templateCode, String workerName, String email, String phone, String account, String password) {
        SdEmailTemplate template = emailTemplateService.getById(templateCode);
        if (template == null) {
            return;
        }
        String content = template.getEmailTemplateContent();
        String replace = content.replace("{新员工}", workerName).replace("{账号}", account).replace("{密码}", password).replace("{链接}", regUrl);
        if (StringUtils.hasText(email)) {
            SdNoticeRecord noticeRecord = new SdNoticeRecord();
            noticeRecord.setNoticeId(IdWorker.nextId() + "");
            noticeRecord.setFlowId("-1");
            noticeRecord.setNoticeType(BusiEnumDefine.NOTICE_TYPE_EMAIL);
            noticeRecord.setTargetName(workerName);
            noticeRecord.setTargetEmail(email);
            noticeRecord.setNoticeTitle(template.getEmailTemplateTitle());
            noticeRecord.setNoticeContent(replace);
            noticeRecord.setCreateTime(new Date());
            asyncSendMessage.sendMessage(Collections.singletonList(noticeRecord));
        } else if (StringUtils.hasText(phone)) {
            SdNoticeRecord noticeRecord = new SdNoticeRecord();
            noticeRecord.setNoticeId(IdWorker.nextId() + "");
            noticeRecord.setFlowId("-1");
            noticeRecord.setNoticeType(BusiEnumDefine.NOTICE_TYPE_SMS);
            noticeRecord.setTargetName(workerName);
            noticeRecord.setTargetPhone(phone);
            noticeRecord.setNoticeContent(replace);
            noticeRecord.setCreateTime(new Date());
            asyncSendMessage.sendMessage(Collections.singletonList(noticeRecord));
        }
    }

    /**
     * 根据身份证url进行ocr
     *
     * @param imgUrl
     * @return
     */
    public OcrDTO idCardOcr(String imgUrl) {
        try {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(commService.getEosMsgToken());
            JSONObject body = new JSONObject();
            body.put("imageUrl", imgUrl);
            HttpEntity<JSONObject> reqEntity = new HttpEntity<>(body, headers);
            ResponseEntity<String> response = restTemplate.exchange(ocrUrl, HttpMethod.POST, reqEntity, String.class);
            String res = response.getBody();
            log.info("身份证OCR识别 地址：" + imgUrl + "===============================");
            log.info(res);
            log.info("==============================================================");
            JSONObject jsonObject = JSONObject.parseObject(res);
            if (jsonObject.get("code").equals(20216)) {
                return JSONObject.parseObject(JSONObject.toJSONString(jsonObject.get("data")), OcrDTO.class);
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据身份证base64进行ocr
     *
     * @param file
     * @return
     */
    public OcrDTO idCardOcrImageBase64(String file) {
        try {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(commService.getEosMsgToken());
            JSONObject body = new JSONObject();
            body.put("imageBase64", file);
            HttpEntity<JSONObject> reqEntity = new HttpEntity<>(body, headers);
            ResponseEntity<String> response = restTemplate.exchange(ocrUrl, HttpMethod.POST, reqEntity, String.class);
            String res = response.getBody();
            log.info("身份证OCR识别 base64===============================");
            log.info(file);
            log.info("--------------------------------------------------------");
            log.info(res);
            log.info("==============================================================");
            JSONObject jsonObject = JSONObject.parseObject(res);
            if (jsonObject.get("code").equals(20216)) {
                return JSONObject.parseObject(JSONObject.toJSONString(jsonObject.get("data")), OcrDTO.class);
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 北森的文件地址前缀需替换才能下载
     *
     * @param dfsUrl
     * @return
     */
    public String replacePicUrl(String dfsUrl) {
        if (StringUtils.hasText(dfsUrl) && dfsUrl.contains("dfs://")) {
            return dfsUrl.replace("dfs://", picPrefix);
        } else {
            return dfsUrl;
        }
    }

    /**
     * ocr结果与北森数据对比
     *
     * @param ocrDTO
     * @param offerWorker
     */
    public void checkOcrResult(OcrDTO ocrDTO, OfferWorker offerWorker) {
        if (StringUtils.hasText(ocrDTO.getName()) && !offerWorker.getWorkerName().equals(ocrDTO.getName())) {
            throw new AppBusinessException("身份证识别姓名与填写的姓名不一致");
        }
        if (StringUtils.hasText(ocrDTO.getIdNum()) && !offerWorker.getCertNo().equals(ocrDTO.getIdNum())) {
            throw new AppBusinessException("身份证识别身份证号与填写的身份证号不一致");
        }
        if (StringUtils.hasText(ocrDTO.getSex()) && !offerWorker.getSex().equals(ocrDTO.getSex())) {
            throw new AppBusinessException("身份证识别性别与填写的性别不一致");
        }
        if (StringUtils.hasText(ocrDTO.getNation()) && !offerWorker.getNation().contains(ocrDTO.getNation())) {
            throw new AppBusinessException("身份证识别民族与填写的民族不一致");
        }
        if (StringUtils.hasText(ocrDTO.getValidDate())) {
            String validDate = ocrDTO.getValidDate();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
            String endDate = validDate.split("-")[1];
            if (!endDate.equals("长期")) {
                try {
                    Date date = sdf.parse(endDate);
                    if (date.compareTo(new Date()) < 0) {
                        throw new AppBusinessException("身份证已过期");
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 校验图片类型
     *
     * @param suffix
     * @return
     */
    public boolean checkImgType(String suffix) {
        return suffix.equals(".bmp")
                || suffix.equals(".jpg")
                || suffix.equals(".png")
                || suffix.equals(".gif")
                || suffix.equals(".tif")
                || suffix.equals(".jfif")
                || suffix.equals(".jpeg")
                || suffix.equals(".tiff");
    }

    /**
     * 北森传来的学历信息附带的图片上传平台sfs并保存到对应study记录上
     *
     * @param url
     * @param fileType
     * @param studyId
     * @return
     */
    public Map<String, String> uploadEducationFiles(String url, Integer fileType, String studyId) {
        Map<String, Object> streamFromUrl = getStreamFromUrl(url, false);
        if (streamFromUrl == null) {
            InputStream inputStream = (InputStream) streamFromUrl.get("inputStream");
            String fileName = (String) streamFromUrl.get("fileName");
            try {
                Map<String, String> retMap = new HashMap<>();
                String fileId = uploadFileToPtability(inputStream, fileName, fileType, studyId);
                retMap.put("fileId",fileId);
                retMap.put("fileName", fileName);
                return retMap;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return new HashMap<>();
    }

    /**
     * 从北森的链接拿文件
     *
     * @param url
     */
    public Map<String, Object> getStreamFromUrl(String url, boolean sendExceptionFlag) {
        url = replacePicUrl(url);
        ResponseEntity<org.springframework.core.io.Resource> response = httpsRestTemplateForUid.getForEntity(url, org.springframework.core.io.Resource.class);
        HttpHeaders headers = response.getHeaders();

        try {
            List<String> headerFileName = headers.get("Content-Disposition");
            if (!CollectionUtils.isEmpty(headerFileName)) {
//                String timeStrNow = DateUtils.dateFormat(new Date(), "yyyyMMddHHmmss");
                String fileName = new String(headerFileName.get(0).getBytes("ISO-8859-1"), "UTF-8").split("=")[1].replaceAll("\"", "");

                InputStream inputStream = response.getBody().getInputStream();
//                File file = new File("download/" + timeStrNow + fileName);
//                FileUtils.copyInputStreamToFile(inputStream, file);
                Map<String, Object> map = new HashMap<>();
                map.put("fileName", fileName);
                map.put("inputStream", inputStream);
                return map;
            } else {
                throw new AppBusinessException("北森文件名获取异常，文件链接：" + url);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (sendExceptionFlag) {
                throw new AppBusinessException("北森文件下载异常，文件链接：" + url);
            }
            return null;
        }
    }

    public Map<String, Object> getStreamFromUrl(String url) {
        url = replacePicUrl(url);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<org.springframework.core.io.Resource> response = null;
        try {
            response = restTemplate.getForEntity(url, org.springframework.core.io.Resource.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (response == null){
            return null;
        }else{
            HttpHeaders headers = response.getHeaders();
        }
        try {
            String fileName = url.substring(url.lastIndexOf("/") + 1);
            InputStream inputStream = response.getBody().getInputStream();
            Map<String, Object> map = new HashMap<>();
            map.put("fileName", fileName);
            map.put("inputStream", inputStream);
            return map;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存北森附件
     *
     * @param buildDTO
     */
    public void saveBeiSenAttachment(BeiSenBuildDTO buildDTO) {
        OfferWorker tbOfferWorker = buildDTO.getTbOfferWorker();
        String workerId = tbOfferWorker.getWorkerId();
        //利益冲突
        String interestConflictPic = tbOfferWorker.getInterestConflictPic();
        //学历学位验证
        String academicDegreeVerifyPics = tbOfferWorker.getAcademicDegreeVerifyPics();
        //学历
        String academicPic = tbOfferWorker.getAcademicPic();
        //学位
        String degreePic = tbOfferWorker.getDegreePic();
        //银行流水
        String bankFlowPic = tbOfferWorker.getBankFlowPic();
        //英语能力
        String englishLevelPic = tbOfferWorker.getEnglishLevelPic();
        if (StringUtils.hasText(interestConflictPic)) {
            for (String url : interestConflictPic.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.INTEREST_CONFLICT);
                }
            }
        }
        if (StringUtils.hasText(academicDegreeVerifyPics)) {
            for (String url : academicDegreeVerifyPics.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.ACADEMIC_DEGREE_VERIFY);
                }
            }
        }
        if (StringUtils.hasText(academicPic)) {
            for (String url : academicPic.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.ACADEMIC);
                }
            }
        }
        if (StringUtils.hasText(degreePic)) {
            for (String url : degreePic.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.DEGREE);
                }

            }
        }
        if (StringUtils.hasText(bankFlowPic)) {
            for (String url : bankFlowPic.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.BANK_FLOW);
                }
            }
        }
        if (StringUtils.hasText(englishLevelPic)) {
            for (String url : englishLevelPic.split(",")) {
                if (StringUtils.hasText(url)) {
                    saveAttachment(workerId, url, TbOfferAttachment.ENGLISH_LEVEL);
                }
            }
        }
    }

    /**
     * 保存北森过来的附件
     *
     * @param preWorkerId
     * @param beiSenUrl
     * @param fileType
     */
    public void saveAttachment(String preWorkerId, String beiSenUrl, Integer fileType) {
        saveAttachment(preWorkerId, beiSenUrl, fileType, true);
    }

    /**
     * 保存北森过来的附件
     *
     * @param preWorkerId
     * @param beiSenUrl
     * @param fileType
     */
    public void saveAttachment(String preWorkerId, String beiSenUrl, Integer fileType, boolean sendExceptionFlag) {
        Map<String, Object> streamFromUrl = getStreamFromUrl(beiSenUrl, sendExceptionFlag);
        if (streamFromUrl == null) {
            return;
        }
        InputStream inputStream = (InputStream) streamFromUrl.get("inputStream");
        String fileName = (String) streamFromUrl.get("fileName");
        String busiId = IdWorker.nextId() + "";
        try {
            String fileId = uploadFileToPtability(inputStream, fileName, fileType, busiId);
            TbOfferAttachment attachment = new TbOfferAttachment();
            attachment.setAttachmentId(busiId);
            attachment.setWorkerId(preWorkerId);
            attachment.setFileType(fileType);
            attachment.setFileId(fileId);
            attachment.setFileName(fileName);
            attachment.setUploadTime(new Date());
            attachment.setAlreadySave(false);
            tbOfferAttachmentMapper.insert(attachment);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public TbOfferAttachment saveAndReturnAttachment(String preWorkerId, String beiSenUrl, Integer fileType, boolean sendExceptionFlag) {
        Map<String, Object> streamFromUrl = getStreamFromUrl(beiSenUrl);
        if (streamFromUrl == null) {
            return new TbOfferAttachment();
        }
        InputStream inputStream = (InputStream) streamFromUrl.get("inputStream");
        String fileName = (String) streamFromUrl.get("fileName");
        String busiId = IdWorker.nextId() + "";
        try {
            String fileId = "-1";
            try {
                fileId = uploadFileToPtability(inputStream, fileName, fileType, busiId);
            } catch (Exception e) {
                log.debug("文件上传sfs异常:" + beiSenUrl);
            }
            TbOfferAttachment attachment = new TbOfferAttachment();
            attachment.setAttachmentId(busiId);
            attachment.setWorkerId(preWorkerId);
            attachment.setFileType(fileType);
            attachment.setFileId(fileId);
            attachment.setFileName(fileName);
            attachment.setUploadTime(new Date());
            attachment.setAlreadySave(false);
            tbOfferAttachmentMapper.insert(attachment);
            return attachment;
        } catch (Exception e) {
            e.printStackTrace();
            return new TbOfferAttachment();
        }
    }

    public String uploadFileToPtability(InputStream inputStream,
                                        String fileName,
                                        Integer busiType,
                                        String busiId) throws IOException {
        String url = abilityUrl + "ptUploadFile/uploadFile";
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", ptToken);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        MultiValueMap<String, Object> reqMap = new LinkedMultiValueMap<>();
        ByteArrayResource resource = new ByteArrayResource(IOUtils.toByteArray(inputStream)) {
            @Override
            public String getFilename() {
                return fileName;
            }
        };

        reqMap.add("uploadFile", resource);
        reqMap.add("clientIP", null);
        reqMap.add("busiType", busiType);
        reqMap.add("busiId", busiId);
        reqMap.add("appId", ptAppId);
        reqMap.add("operatorId", "system");
        reqMap.add("operatorName", "system");
        HttpEntity<MultiValueMap<String, Object>> body = new HttpEntity(reqMap, headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, body, String.class);
        String resBody = response.getBody();
        JSONObject jsonObject = JSONObject.parseObject(resBody);
        if (jsonObject.get("code").equals(20000)) {
            JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(jsonObject.get("data")));
            return data.getString("fileId");
        } else {
            throw new AppBusinessException("北森文件上传平台异常");
        }
    }

    public int updateSapNationPlaceForWorker() {
        LambdaQueryWrapper<TbOfferWorker> offerWorkerWrapper = new LambdaQueryWrapper<>();
        offerWorkerWrapper.isNotNull(TbOfferWorker::getRegularWorkerId).ge(TbOfferWorker::getRegularWorkerId, "29737");
        List<TbOfferWorker> tbOfferWorkers = tbOfferWorkerMapper.selectList(offerWorkerWrapper);
        List<String> workerIds = tbOfferWorkers.stream().map(TbOfferWorker::getWorkerId).collect(Collectors.toList());
        return updateSapNationPlace(workerIds);
    }

    @SneakyThrows
    public int updateSapNationPlace(List<String> workerIds) {
        int count = 0;
        //人员编号  I_PERNR
        //开始日期  I_BEGDA
        //结束日期  I_ENDDA
        //籍贯      I_GBORT
        //民族      I_RACKY
        //政治面貌  I_PCODE
        List<PtEnumDTO> nation = EnumUtil.getEnums("NEW_STAFF_ORIGIN");
        Map<String, String> nationMap = new HashMap<>();
        nation.forEach(o -> {
            nationMap.put(o.getValue(), o.getNameZh());
        });
        SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMdd");
        String format = sdf.format(new Date());
        List<TbOfferWorker> tbOfferWorkers = tbOfferWorkerMapper.selectBatchIds(workerIds);
        rfcManager.connect();
        JCoDestination destination = rfcManager.getDestination();
        for (TbOfferWorker offerWorker : tbOfferWorkers) {
            if (StringUtils.hasText(offerWorker.getRegularWorkerId())) {
                try {
                    JCoFunction func = rfcManager.getFunction(destination, "ZHR_BASIC_OPERATION");
                    JCoParameterList paramObj = func.getImportParameterList();
                    paramObj.setValue("I_PERNR", offerWorker.getRegularWorkerId());
                    paramObj.setValue("I_BEGDA", format);
                    paramObj.setValue("I_ENDDA", "99991231");
                    paramObj.setValue("I_RACKY", offerWorker.getNation());
                    paramObj.setValue("I_PCODE", offerWorker.getPoliticalLandscape());
                    paramObj.setValue("I_GBORT", StringUtils.hasText(offerWorker.getNationPlace()) ? nationMap.get(offerWorker.getNationPlace()) : "");
                    func.execute(destination);
                    JCoParameterList exportParameterList = func.getExportParameterList();
                    String type = exportParameterList.getStructure("E_RETURN").getString("TYPE");
                    if ("S".equals(type)) {
                        count++;
                    }
                    sdRequestRecordService.addReqRecord(offerWorker.getRegularWorkerId(), RequestEnum.更新正式员工籍贯.getName(), RequestEnum.更新正式员工籍贯.getUrl(), paramObj.toXML(), exportParameterList.toXML());
                } catch (Exception e) {
                    log.error("{}",e);
                }
            }
        }
        return count;
    }
}
